﻿using System.Diagnostics;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Antiforgery;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.Extensions.DependencyInjection;
using StackExchange.Exceptional;
using WB.Core.GenericSubdomains.Portable;
using WB.Core.SharedKernels.DataCollection.Exceptions;
using WB.Enumerator.Native.WebInterview;
using WB.UI.Headquarters.Models.WebInterview;

namespace WB.UI.Headquarters.Filters
{
    public class WebInterviewErrorFilterAttribute : ExceptionFilterAttribute
    {
        private readonly ITempDataDictionaryFactory tempDataDictionaryFactory;

        public WebInterviewErrorFilterAttribute(ITempDataDictionaryFactory tempDataDictionaryFactory)
        {
            this.tempDataDictionaryFactory = tempDataDictionaryFactory;
        }

        public override void OnException(ExceptionContext filterContext)
        {
            var interviewException = filterContext.Exception.GetSelfOrInnerAs<InterviewException>();
            if (interviewException != null
                && interviewException.ExceptionType != InterviewDomainExceptionType.Undefined)
            {
                string errorMessage = WebInterview.GetUiMessageFromException(interviewException);

                this.HandleInterviewAccessError(filterContext, errorMessage);
                return;
            }
            if (filterContext.Exception is AntiforgeryValidationException)
            {
                this.HandleInterviewAccessError(filterContext, Enumerator.Native.Resources.WebInterview.Error_CookiesTurnedOff);
                return;
            }

            if (filterContext.Exception is InterviewAccessException interviewAccessException)
            {
                if (interviewAccessException.Reason == InterviewAccessExceptionReason.UserNotAuthorised)
                {
                    filterContext.ExceptionHandled = true;
                    filterContext.HttpContext.Response.Clear();
                    filterContext.HttpContext.Response.StatusCode = 401;
                    filterContext.Result = new ContentResult
                    {
                        Content = "User is Not Authorized"
                    };

                    return;
                }

                if (interviewAccessException.Reason == InterviewAccessExceptionReason.Forbidden)
                {
                    filterContext.ExceptionHandled = true;
                    filterContext.HttpContext.Response.Clear();
                    filterContext.HttpContext.Response.StatusCode = 403;
                    filterContext.Result = new ContentResult
                    {
                        Content = "Forbidden"
                    };
                    return;
                }

                this.HandleInterviewAccessError(filterContext, interviewAccessException.Message);
                return;
            }

            filterContext.Exception.Log(filterContext.HttpContext);
            this.HandleInDebugMode(filterContext);
        }

        [Conditional("DEBUG")]
        private void HandleInDebugMode(ExceptionContext filterContext)
        {
            filterContext.ExceptionHandled = true;

            filterContext.Result = new ContentResult
            {
                Content = $@"
<h1>No <b>Index.cshtml<b> found in ~Views\WebInterview folder.</h1>
<p>Index.cshtml is generated by 'WB.UI.Headquarters.Interview' application build. </p>
<p>Please navigate to WB.UI.Headquarters.Interview folder and run following commands that will install all nodejs deps and run dev server</p>
<pre>
npm install 
npm run dev
</pre>
Exception details:<br />
<pre>{filterContext.Exception}</pre>"
            };
        }

        private void HandleInterviewAccessError(ExceptionContext filterContext, string message)
        {
            var tempData = tempDataDictionaryFactory.GetTempData(filterContext.HttpContext);
            tempData["WebInterview.ErrorMessage"] = message;
            filterContext.Result = new RedirectToActionResult("Error", "WebInterview", new WebInterviewError { ErrorMessage = message });
            filterContext.ExceptionHandled = true;
        }
    }
}
